﻿using PMS.Core.Configuration;
using PMS.Core.Configuration.CommonEnumConfigs;

namespace PMS.Data.Entities.Settings
{
    /// <summary>
    /// Customer settings
    /// </summary>
    public class CustomerSettings : ISettings
    {
        private const int DEFAULTCHANGEPASSWORDDEADLINE = 5;
        private int _changepassworddeadline;
        /// <summary>
        /// 账号验证方式：Jwt / Cookie
        /// </summary>
        public AuthenticationType AccountAuthenticationType { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether users are allowed to change their usernames
        /// </summary>
        public bool AllowUsersToChangeUsernames { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether username will be validated (when registering or changing on the 'My Account' page)
        /// </summary>
        public bool UsernameValidationEnabled { get; set; }

        /// <summary>
        /// Gets or sets a username validation rule
        /// </summary>
        public string UsernameValidationRule { get; set; }

        /// <summary>
        /// Messages Hint when username validation failed 
        /// </summary>
        public string UsernameValidationTips { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether phone number will be validated (when registering or changing on the 'My Account' page)
        /// </summary>
        public bool PhoneNumberValidationEnabled { get; set; }

        /// <summary>
        /// Gets or sets a phone number validation rule
        /// </summary>
        public string PhoneNumberValidationRule { get; set; }

        /// <summary>
        /// Messages Hint when Phone/Mobile validation failed 
        /// </summary>
        public string PhoneNumberValidationTips { get; set; }

        /// <summary>
        /// Default password format for customers
        /// </summary>
        public PasswordFormat DefaultPasswordFormat { get; set; }

        /// <summary>
        /// Gets or sets a customer password format (SHA1, MD5) when passwords are hashed (DO NOT edit in production environment)
        /// </summary>
        public string HashedPasswordFormat { get; set; }

        /// <summary>
        /// Gets or sets a number of days for password recovery link. Set to 0 if it doesn't expire.
        /// </summary>
        public int PasswordRecoveryLinkDaysValid { get; set; }

        /// <summary>
        /// Gets or sets a minimum password length
        /// </summary>
        public int PasswordMinLength { get; set; }
        /// <summary>
        /// Gets or sets a maximum password length
        /// </summary>
        public int PasswordMaxLength { get; set; }
        /// <summary>
        /// Gets or sets a value indicating whether password are have least one lowercase
        /// </summary>
        public bool PasswordRequireLowercase { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether password are have least one uppercase
        /// </summary>
        public bool PasswordRequireUppercase { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether password are have least one non alphanumeric character
        /// like !@#$%^&*()_+=\[{\]};:<>|./?,-
        /// </summary>
        public bool PasswordRequireSpecialCharacter { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether password are have least one digit
        /// </summary>
        public bool PasswordRequireDigit { get; set; }

        /// <summary>
        /// Gets or sets a number of days for password expiration
        /// set 0(zero) to disable Password Expire Check
        /// </summary>
        public int PasswordLifetime { get; set; }

        /// <summary>
        /// Gets or sets maximum login failures to lockout account. Set 0 to disable this feature
        /// </summary>
        public int FailedPasswordAllowedAttempts { get; set; }

        /// <summary>
        /// Gets or sets a value indicating total number of failed login attempts (wrong password)
        /// 通过CustomerSettings.FailedPasswordAllowedAttempts 设置的允许密码错误次数配合使用
        /// 当登录密码超过指定次数时，锁定账号：
        /// 1：设置限制登录时间 CannotLoginUntilDateUtc, 在限制时间未到之前不允许登录
        ///   通过CustomerSettings.FailedPasswordLockoutMinutes计算限制登录时长
        /// 2：如果限制登录时间到后重登录依然校验密码错误，设置下次限制登录时长同时累加错误登录次数
        ///  到达CustomerSettings.TotalFailedAllowedAttemps所设置的允许登录错误尝试次数后，不再设置下次限制登录时长，
        ///  而是锁定账号 IsActive=true,锁定账号后只能后台系统有用户操作权限的账号重置密码或者用户通过"忘记密码"功能重置密码
        /// </summary>
        public int TotalFailedAllowedAttemps { get; set; }
        /// <summary>
        /// Gets or sets a number of minutes to lockout users (for login failures).
        /// </summary>
        public int FailedPasswordLockoutMinutes { get; set; }

        /// <summary>
        /// Gets or sets a maximum avatar size (in bytes)
        /// </summary>
        public int AvatarMaximumSizeBytes { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether customers location is shown
        /// </summary>
        public bool ShowCustomersLocation { get; set; }

        /// <summary>
        /// 登录用户浏览网页时，间隔一定时间触发记录操作时间
        /// 用以判断是否在线
        /// </summary>
        public int LastActivityMinutes { get; set; }

        /// <summary>
        /// Gets or sets a value indicating the number of minutes for 'online customers' module
        /// </summary>
        public int OnlineCustomerMinutes { get; set; }

        public bool StoreLastVisitedPage { get; set; }
        /// <summary>
        /// User registration type
        /// </summary>
        public UserRegistrationType UserRegistrationType { get; set; }

        /// DavidLee 更改检查密码过期检查机制，判断密码过期时效，返回密码过期天数。
        /// 在容错期时间段内，只提醒用户更改密码，在容错期后强制要求用户更改密码
        public int ForceChangePasswordDeadline 
        {
            get
            {
                if (_changepassworddeadline <= 0) return DEFAULTCHANGEPASSWORDDEADLINE;
                return _changepassworddeadline;
            }
            set => _changepassworddeadline = value;
        }
    }
}
